package uy.edu.um.ltic.server.communication;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import uy.edu.um.ltic.exception.DataBaseException;
import uy.edu.um.ltic.commons.UtilUs;
import uy.edu.um.ltic.server.persistence.ConferenceRemStarDAOFactory;
import uy.edu.um.ltic.server.persistence.ConferenceRemStarDAOMgt;
import uy.edu.um.ltic.server.persistence.EmployeeDAOFactory;
import uy.edu.um.ltic.server.persistence.PendingDAOFactory;
import uy.edu.um.ltic.server.persistence.PendingDAOMgt;

public class ServerSocket {

	private static Map<String, Connection> conMap = new HashMap<String, Connection>();

	// private static Map<String, ArrayList<String>> pendingText = new
	// HashMap<String, ArrayList<String>>();

	public static void dropConnection(String nEmpl){
		conMap.remove(nEmpl);
	}
	
	
	public static void notifyClients(String sToUser, String sFrom, String action)
			throws DataBaseException {
		if (conMap.get(sToUser) != null) {
			PrintWriter pw = conMap.get(sToUser).getPw();
			if (action.equals("refrChat")) {
				pw.write("refrChat\n");
				pw.write(sFrom + "\n");
				pw.flush();
			} else if (action.equals("refrChatConf")) {
				pw.write("refrChatConf\n");
				pw.write(sFrom + "\n");
				pw.flush();
			} else if (action.equals("remConf")) {
				pw.write("remConf\n");
				pw.write(sFrom + "\n");
				pw.flush();
			} else if (action.equals("startConf")) {
				pw.write("startConf\n");
				pw.write(sFrom + "\n");
				pw.flush();
			}
		} else {
			int sToUserInt = new Integer(sToUser);
			int sFromInt = new Integer(sFrom);

			if (action.equals("refrChat")) {
				if (PendingDAOFactory.getInstance().getPendingDAOMgt()
						.getPendingTextMessages(sToUserInt).size() == 0) {
					boolean yaesta = false;
					for (int pendFr : PendingDAOFactory.getInstance()
							.getPendingDAOMgt()
							.getPendingTextMessages(sToUserInt)) {
						if (pendFr == sFromInt) {
							yaesta = true;
						}
					}
					if (!yaesta) {

						PendingDAOFactory.getInstance().getPendingDAOMgt()
								.addPendingTextMessages(sToUserInt, sFromInt);

					}
				}
			} else if (action.equals("refrChatConf")) {
				if (PendingDAOFactory.getInstance().getPendingDAOMgt()
						.getPendingConferenceMessages(sToUserInt).size() != 0) {
					boolean yaesta = false;
					for (int pendFr : PendingDAOFactory.getInstance()
							.getPendingDAOMgt()
							.getPendingConferenceMessages(sToUserInt)) {
						if (pendFr == sFromInt) {
							yaesta = true;
						}
					}
					if (!yaesta) {

						PendingDAOFactory
								.getInstance()
								.getPendingDAOMgt()
								.addPendingConferenceMessages(sToUserInt,
										sFromInt);

					}

				} else {
					PendingDAOFactory.getInstance().getPendingDAOMgt()
							.addPendingConferenceMessages(sToUserInt, sFromInt);

				}
			} else if (action.equals("remConf")) {
				//ConferenceRemStarDAOFactory.getInstance()
				//		.getConferenceRemStarDAOMgt()
				//		.addReminder(sToUserInt, sFromInt);
			} else if (action.equals("startConf")) {
				boolean yaexiste = false;
				for (Integer idConf : ConferenceRemStarDAOFactory.getInstance()
						.getConferenceRemStarDAOMgt().getStartConf(sToUserInt)) {
					if (idConf.compareTo(sFromInt) == 0) {
						yaexiste = true;
					}
				}
				if (!yaexiste) {
					ConferenceRemStarDAOFactory.getInstance()
							.getConferenceRemStarDAOMgt()
							.addStartConf(sToUserInt, sFromInt);
				}
			}

		}

	}

	public static void aceptarConexiones() throws DataBaseException {

		BufferedReader br;

		/** For writing output to socket. */
		PrintWriter pw;
		try {

			java.net.ServerSocket oServerSocket = new java.net.ServerSocket(
					7899);
			System.out.println("Server ON");
			while (true) {

				System.out.println("Accepting connections...");
				Socket oSocket = oServerSocket.accept();
				System.out.println("Client acepted!");
				br = new BufferedReader(new InputStreamReader(
						oSocket.getInputStream()));

				pw = new PrintWriter(oSocket.getOutputStream(), true);
				pw.write("Quienso\n");
				pw.flush();
				String sUser = br.readLine();
				String sPass = br.readLine();
				String tPass = EmployeeDAOFactory.getInstance()
						.getEmployeeDAOMgt().getEmployeeLogIn(sUser)
						.getPassword();
				String tSalt = EmployeeDAOFactory.getInstance()
						.getEmployeeDAOMgt().getEmployeeLogIn(sUser).getSalt();
				boolean ok = (tPass.equals(UtilUs.getSecurePassword(sPass,
						tSalt)));
				if (ok) {
					String nEmpl = Integer.toString(EmployeeDAOFactory
							.getInstance().getEmployeeDAOMgt()
							.getEmployeeLogIn(sUser).getnEmployee());
					Integer nEmplInt = new Integer(nEmpl);
					Connection oCon = new Connection(br, pw, oSocket);
					conMap.put(nEmpl, oCon);
					PendingDAOMgt pend = PendingDAOFactory.getInstance()
							.getPendingDAOMgt();
					ConferenceRemStarDAOMgt confRS = ConferenceRemStarDAOFactory
							.getInstance().getConferenceRemStarDAOMgt();

					if (pend.getPendingTextMessages(nEmplInt).size() != 0) {
						ArrayList<Integer> pen = pend
								.getPendingTextMessages(nEmplInt);
						for (Integer sFrom : pen) {
							pw.write("refrChat\n");
							pw.write(sFrom + "\n");
							pw.flush();
						}
						pend.deletePendingTextMessages(nEmplInt);
					}

					if (pend.getPendingConferenceMessages(nEmplInt).size() != 0) {
						ArrayList<Integer> pen = pend
								.getPendingConferenceMessages(nEmplInt);
						for (Integer iDConf : pen) {
							pw.write("refrChatConf\n");
							pw.write(iDConf + "\n");
							pw.flush();
						}
						pend.deletePendingConferenceMessages(nEmplInt);
					}

					/*
					 * if(confRS.getReminder(nEmplInt).size()!=0){
					 * ArrayList<Integer> pen = confRS.getReminder(nEmplInt);
					 * for(Integer iDConf : pen){ pw.write("remConf\n");
					 * pw.write(iDConf+ "\n"); pw.flush(); }
					 * confRS.deleteReminder(nEmplInt);
					 * 
					 * }
					 */
					if (confRS.getStartConf(nEmplInt).size() != 0) {
						ArrayList<Integer> pen = confRS.getStartConf(nEmplInt);
						for (Integer iDConf : pen) {
							pw.write("startConf\n");
							pw.write(iDConf + "\n");
							pw.flush();
						}
						confRS.deleteStartConf(nEmplInt);
					}
				} else {
					//pw.write("Access Denied");
					//pw.flush();
					System.out.println("Access Denied");
				}

			}

			// oSocket.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static void levantarServerSocket() {

		Thread oThread = new Thread(new Runnable() {

			@Override
			public void run() {

				try {
					ServerSocket.aceptarConexiones();
				} catch (DataBaseException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}
		});
		oThread.start();

		try {

			Thread.sleep(30000);

		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
}